
#include "SMBUS_Define.h"
#include  "..\ESS_CommonDefine.h"


char I2C_Status_UCB2;
char I2C_UCB2_WR_NoStopFlag;

unsigned char *PTxData_UCB2;                     // Pointer to TX data
unsigned char TXByteCtr_UCB2;


unsigned char *PRxData_UCB2;                     // Pointer to RX data
unsigned char RXByteCtr_UCB2;
unsigned char TRxData_UCB2[TRX_DataBuffer];


void Init_USCI_B2_IIC()
{
  P9SEL |= 0x06;                            // Assign I2C pins to USCI_B2: P9.1 , P9.2
  UCB2CTL1 |= UCSWRST;                      // Enable SW reset
  UCB2CTL0 = UCMST + UCMODE_3 + UCSYNC;     // I2C Master, synchronous mode
  UCB2CTL1 = UCSSEL_2 + UCSWRST;            // Use SMCLK, keep SW reset
  UCB2BR0 = 12;                             // fSCL = SMCLK/12 = ~100kHz
  UCB2BR1 = 0;
  UCB2CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation

  UCB2I2CSA = DEVICE_ADDRESS;               // Slave Address
  
  //UCB2IE |= UCTXIE + UCRXIE + UCNACKIE;                         // Enable TX & RX interrupt
  UCB2IE |= UCTXIE;                         // Enable TX interrupt
  UCB2IE |= UCNACKIE;                         //NACK Condition interrupt enable
  UCB2IE |= UCRXIE;                         //USCI Receive Interrupt Enable
  UCB2IE |= UCALIE;                         //Arbitration Lost interrupt enable
  I2C_Status_UCB2 = None;
  I2C_UCB2_WR_NoStopFlag = false;
}

char SMBUS2_WriteWord_PEC(unsigned char command, unsigned char *WriteData){
  
  unsigned char PEC, temp, i;

  I2C_UCB2_WR_NoStopFlag =false;
  
  PEC = 0x00;
  temp = (DEVICE_ADDRESS << 1);
  PEC = CRC8LookUp[PEC ^ temp];

  TRxData_UCB2[0] = command;
  PEC = CRC8LookUp[PEC ^ command];

  for(i=0; i<2; i++){
    PEC = CRC8LookUp[PEC ^ *WriteData];
    TRxData_UCB2[i+1] = *WriteData++;
  }
  TRxData_UCB2[3] = PEC;
  
  return MasterIIC_Write_UCB2(TRxData_UCB2, 4);
}
char SMBUS2_ReadWord_PEC(unsigned char command, unsigned char *ReadData){

  unsigned char PEC, temp, i;
	unsigned char I2C_Temp_Status;
  
  I2C_UCB2_WR_NoStopFlag =true;
  
  TRxData_UCB2[0] = command;
  I2C_Temp_Status = MasterIIC_Write_UCB2(TRxData_UCB2, 1);
  if(I2C_Temp_Status){
    return I2C_Temp_Status;
  }
  
  
  //__delay_cycles(500);// Delay us
  I2C_Temp_Status = MasterIIC_Read_UCB2(TRxData_UCB2,3);
  if(I2C_Temp_Status){
    return I2C_Temp_Status;
  }
  
  PEC = 0x00;
  temp = (DEVICE_ADDRESS << 1) + 1;
  PEC = CRC8LookUp[PEC ^ temp];

  for(i=0; i<2; i++){
    PEC = CRC8LookUp[PEC ^ TRxData_UCB2[i]];
  }
  if(PEC != TRxData_UCB2[2]){
    return I2cPECFail;
  }
  for(i=0; i<2; i++){
    *ReadData++ = TRxData_UCB2[i];
  }
  return None;  
}



char SMBUS2_WriteBlock_PEC_err(unsigned char command, unsigned char *WriteData, unsigned char DataLength ){
  
  unsigned char PEC, temp, i;

  I2C_UCB2_WR_NoStopFlag =false;
  
  PEC = 0x00;
  temp = (DEVICE_ADDRESS << 1);
  PEC = CRC8LookUp[PEC ^ temp];

  TRxData_UCB2[0] = command;
  PEC = CRC8LookUp[PEC ^ command];
  TRxData_UCB2[1] = DataLength;
  PEC = CRC8LookUp[PEC ^ DataLength];  
  
  if(DataLength >= TRX_DataBuffer - 3){
    return I2cDataLengthFail;
  }
  for(i=0; i<DataLength; i++){
    PEC = CRC8LookUp[PEC ^ *WriteData];
    TRxData_UCB2[i+2] = *WriteData++;
  }
  TRxData_UCB2[DataLength+2] = PEC + 1;
  
  return MasterIIC_Write_UCB2(TRxData_UCB2, DataLength + 3);
}
char SMBUS2_WriteBlock_PEC(unsigned char command, unsigned char *WriteData, unsigned char DataLength ){
  
  unsigned char PEC, temp, i;

  I2C_UCB2_WR_NoStopFlag =false;
  
  PEC = 0x00;
  temp = (DEVICE_ADDRESS << 1);
  PEC = CRC8LookUp[PEC ^ temp];

  TRxData_UCB2[0] = command;
  PEC = CRC8LookUp[PEC ^ command];
  TRxData_UCB2[1] = DataLength;
  PEC = CRC8LookUp[PEC ^ DataLength];  
  
  if(DataLength >= TRX_DataBuffer - 3){
    return I2cDataLengthFail;
  }
  for(i=0; i<DataLength; i++){
    PEC = CRC8LookUp[PEC ^ *WriteData];
    TRxData_UCB2[i+2] = *WriteData++;
  }
  TRxData_UCB2[DataLength+2] = PEC;
  
  temp = MasterIIC_Write_UCB2(TRxData_UCB2, DataLength + 3);
  
  //Delay for Writing data in
  for(i = 0; i < 10; i++){
    __delay_cycles(5000);
  }
  return temp;
}
char SMBUS2_ReadBlock_PEC(unsigned char command, unsigned char *ReadData, unsigned char *DataLength){

  unsigned char PEC, temp, i;
	unsigned char I2C_Temp_Status;
  
  I2C_UCB2_WR_NoStopFlag =false;
  
  TRxData_UCB2[0] = command;
  I2C_Temp_Status = MasterIIC_Write_UCB2(TRxData_UCB2, 1);
  if(I2C_Temp_Status){
    return I2C_Temp_Status;
  }
  
  
  I2C_Temp_Status = MasterIIC_Read_UCB2(TRxData_UCB2,TRX_DataBuffer);
  if(I2C_Temp_Status){
    return I2C_Temp_Status;
  }
  
  PEC = 0x00;
  temp = (DEVICE_ADDRESS << 1) + 1;
  PEC = CRC8LookUp[PEC ^ temp];
  PEC = CRC8LookUp[PEC ^ TRxData_UCB2[0]];

  temp = TRxData_UCB2[0] + 1;
  for(i=1; i<temp; i++){
    PEC = CRC8LookUp[PEC ^ TRxData_UCB2[i]];
  }
  if(PEC != TRxData_UCB2[temp]){
    return I2cPECFail;
  }
  for(i=1; i<temp; i++){
    *ReadData++ = TRxData_UCB2[i];
  }
  *DataLength = TRxData_UCB2[0];
  return None;  
  
}

//******************************************************************************
//  USCI_B2 I2C Master TX multiple bytes to Slave
//  an I2C master transmitter sending multiple bytes using the USCI_B2 TX interrupt.
//  ACLK = n/a, MCLK = SMCLK = BRCLK = default DCO = ~1.045MHz
//******************************************************************************
char MasterIIC_Write_UCB2(unsigned char *PTxData, unsigned char TXByteCtr)
{
  unsigned int i;
  unsigned int cout;
  I2C_Status_UCB2 = None;
  //while (UCB2CTL1 & UCTXSTP);             // Ensure stop condition got sent

  //while (UCB2STAT & UCBBUSY) {  // Wait for I2C-bus to be free
  i=0;
  while (UCB2STAT) {  // Wait for I2C-bus to be free
    i++;
    //__delay_cycles(500);// Delay us
    if(i > WAIT_COUNT)
    {
      Init_USCI_B2_IIC();
      __delay_cycles(10);// Delay us
      if(UCB2STAT){
        I2C_Status_UCB2 = I2cBusUnavailable;
        TXByteCtr_UCB2=0;
        return I2C_Status_UCB2;
      }else{
        break;
      }
    }       
  }   

  PTxData_UCB2 = PTxData;      // TX array start address
  TXByteCtr_UCB2 = TXByteCtr;
  UCB2CTL1 |= UCTR + UCTXSTT;             // I2C TX, start condition
  
  i=0;
  
  if(TXByteCtr_UCB2 > 1){
   //__bis_SR_register(LPM0_bits + GIE);
  }
  __no_operation();
  cout = WAIT_COUNT * TXByteCtr;
   
  while(!I2C_Status_UCB2){
    i++;
    if(i > cout)  
    {
      TXByteCtr_UCB2 = 0;
      UCB2CTL1 |= UCTXSTP;                    // Generate I2C stop condition
      I2C_Status_UCB2 = I2cWriteFail;
      return I2C_Status_UCB2;
    }    
  }
  i=0;
  while (UCB2CTL1 & UCTXSTP)             // Ensure stop condition got sent
  {
    if(I2C_Status_UCB2 == NoRespondence){
      UCB2CTL1 &= ~UCTXSTP;
    }
    if(I2C_Status_UCB2 == Done){
      i++;
      if(i > cout)  
      {
        TXByteCtr_UCB2 = 0;
        UCB2CTL1 &= ~UCTXSTP; 
        I2C_Status_UCB2 = I2cWriteFail;
        return I2C_Status_UCB2;
      }    
    }
  }  
  if(I2C_Status_UCB2 == NoRespondence){
    UCB2CTL1 &= ~UCTXSTP;
    return I2C_Status_UCB2;
  }else if (I2C_Status_UCB2 == Done){
    return None;
  }else{
    return I2cWriteFail;
  }
}

//******************************************************************************
// USCI_B2 I2C Master RX multiple bytes from MSP430 Slave
//  an I2C master receiver receiving multiple bytes using the USCI_B2 TX interrupt.
//  ACLK = n/a, MCLK = SMCLK = BRCLK = default DCO = ~1.045MHz
//******************************************************************************
char MasterIIC_Read_UCB2(unsigned char *PRxData,unsigned char RXByteCtr)
{
  unsigned int i;
  unsigned int cout;
  I2C_Status_UCB2 = None;
  //while (UCB2CTL1 & UCTXSTP);             // Ensure stop condition got sent
  //while (UCB2STAT & UCBBUSY) {  // Wait for I2C-bus to be free
  i=0;
  while (UCB2STAT) {  // Wait for I2C-bus to be free
   i++;
    //__delay_cycles(500);
    __delay_cycles(100);
    if(i > WAIT_COUNT)
    {
      Init_USCI_B2_IIC();
      I2C_Status_UCB2 = I2cBusUnavailable;
      RXByteCtr_UCB2=0;
      return I2C_Status_UCB2;
    }       
  }   
  PRxData_UCB2 = PRxData;      // TX array start address
  RXByteCtr_UCB2 = RXByteCtr;

  UCB2CTL1 &= ~UCTR;             // I2C RX mode
  UCB2CTL1 |= UCTXSTT;             // I2C RX, start condition
  if(RXByteCtr == 1){
    while(UCB2CTL1 & UCTXSTT);              // Start condition sent?
    UCB2CTL1 |= UCTXSTP;                    // I2C stop condition
    RXByteCtr = 0;
  }
  
  i=0;
  if(RXByteCtr > 1){
     //__bis_SR_register(LPM0_bits + GIE);
     //__bis_SR_register(LPM0_bits);
  }
  __no_operation();
  cout = WAIT_COUNT * RXByteCtr;
  while(!I2C_Status_UCB2){
    i++;
    if(i > cout)  
    {
      RXByteCtr_UCB2 = 0;
      UCB2CTL1 |= UCTXSTP;                    // Generate I2C stop condition
      I2C_Status_UCB2 = I2cReadFail;
      return I2C_Status_UCB2;
    }    
  }  

  if(I2C_Status_UCB2 == NoRespondence){
    UCB2CTL1 &= ~UCTXSTP;
    return I2C_Status_UCB2;
  }else if (I2C_Status_UCB2 == Done){
    return None;
  }else{
    return I2cReadFail;
  }
}

char IIC_WR2(unsigned char *PTxData, unsigned char TXByteCtr, unsigned char *PRxData,unsigned char RXByteCtr, unsigned char retryCount){
    unsigned int retry = 0;
    

    do //for retry
    {
      I2C_Status_UCB2 = SMBUS2_ReadWord_PEC(PTxData[0], PRxData);
      
      //I2C_Status_UCB2 = MasterIIC_Write_UCB2(PTxData, TXByteCtr);
      //I2C_Status_UCB2 |= MasterIIC_Read_UCB2(PRxData,RXByteCtr);
      if(I2C_Status_UCB2 == None){
        I2C_Status_UCB2 = None;
        break;
      }
      __no_operation();
    }while(++retry < retryCount);
    
    
    return I2C_Status_UCB2;
}

//------------------------------------------------------------------------------
// The USCIAB0TX_ISR is structured such that it can be used to transmit any
// number of bytes by pre-loading TXByteCtr with the byte count. Also, TXData
// points to the next byte to transmit.
//------------------------------------------------------------------------------
#pragma vector = USCI_B2_VECTOR
__interrupt void USCI_B2_ISR(void)
{
  switch(__even_in_range(UCB2IV,12))
  {
  case  0: break;                           // Vector  0: No interrupts
  case  2:                                 // Vector  2: ALIFG
    I2C_Status_UCB2 = I2cAlFail;
    break;
  case  4:                                  // Vector  4: NACKIFG
    //P1OUT = 0x02;//LED
    UCB2IFG &= ~UCNACKIFG;                  // Clear USCI_B2 NACK int flag
    if(UCB2CTL1 & UCTR)
    {
      //TX
      UCB2CTL1 |= UCTXSTP;                    // Generate I2C stop condition
    }else
    {
      //RX
      if(RXByteCtr_UCB2 != 1){
        UCB2CTL1 |= UCTXSTP;                    // Generate I2C stop condition
      }
    }
    RXByteCtr_UCB2 = 0;
    TXByteCtr_UCB2 = 0;
    I2C_Status_UCB2 = NoRespondence;
    //__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
    break;
  case  6: break;                           // Vector  6: STTIFG
  case  8: break;                           // Vector  8: STPIFG
  case 10:                                  // Vector 10: RXIFG

    *PRxData_UCB2++ = UCB2RXBUF; 
    RXByteCtr_UCB2--;
    if (RXByteCtr_UCB2 == 1)
    {
       UCB2CTL1 |= UCTXSTP;
    }
    if (RXByteCtr_UCB2 == 0){
      I2C_Status_UCB2 = Done;
      //__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
    }
    break;
  case 12:                                  // Vector 12: TXIFG
    if (TXByteCtr_UCB2)                          // Check TX byte counter
    {
      UCB2TXBUF = *PTxData_UCB2++;               // Load TX buffer
      TXByteCtr_UCB2--;                          // Decrement TX byte counter
    }
    else
    {

      if(!I2C_UCB2_WR_NoStopFlag){
        UCB2CTL1 |= UCTXSTP;                  // I2C stop condition
      }
      UCB2IFG &= ~UCTXIFG;                  // Clear USCI_B2 TX int flag
      I2C_Status_UCB2 = Done;
      //__bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
      //__bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
    }
    
    break;
  default: break;
  }
}

